﻿using System;
using System.Collections.Concurrent;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Serialization;
using Jeelu.Exceptions;

namespace Jeelu
{
    public static class UtilitySerialize
    {
        private static readonly ConcurrentDictionary<string, XmlSerializer> _SerializerMap = new ConcurrentDictionary<string, XmlSerializer>();

        /// <summary>XmlSerializer的实例的生成效率不高，故保存已生成的实例，以提高效率。
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        internal static XmlSerializer GetSerializer(Type type)
        {
            string fullname = type.FullName;
            if (string.IsNullOrWhiteSpace(fullname))
                throw new SerializationException(string.Format("无法为类型:{0}创建序列化。", type.Name));
            XmlSerializer serializer;
            if (!_SerializerMap.TryGetValue(fullname, out serializer))
            {
                serializer = new XmlSerializer(type);
                _SerializerMap.TryAdd(fullname, serializer);
            }
            return serializer;
        }

        public static string Serialize(object o)
        {
            Type type = o.GetType();
            XmlSerializer serializer = GetSerializer(type);
            var sb = new StringBuilder();
            try
            {
                var writer = new StringWriter(sb);
                serializer.Serialize(writer, o);
            }
            catch (Exception e)
            {
                throw new SerializationRuntimeException("序列化一个对象时异常", e);
            }
            return sb.ToString();
        }

        public static T Deserialize<T>(string xml)
        {
            try
            {
                Type type = typeof (T);
                XmlSerializer serializer = GetSerializer(type);
                var sr = new StringReader(xml);
                object obj = serializer.Deserialize(sr);
                return (T) obj;
            }
            catch (Exception e)
            {
                throw new SerializationRuntimeException("反序列化时异常", e);
            }
        }

        public static object Deserialize(string xml, Type type)
        {
            try
            {
                XmlSerializer serializer = GetSerializer(type);
                var sr = new StringReader(xml);
                object obj = serializer.Deserialize(sr);
                return obj;
            }
            catch (Exception e)
            {
                throw new SerializationRuntimeException("反序列化时异常", e);
            }
        }
    }
}